#pragma once
#ifndef _COMM_HPP_
    #define _COMM_HPP_

    #include <iostream>
    #include <cstdio>
    #include <cerrno>
    #include <cstdlib>
    #include <cstring>
    #include <unistd.h>
    #include <sys/ipc.h>
    #include <sys/shm.h>
    #include <sys/types.h>

    #define PATHNAME "."
    #define PROJ_ID 0x66
    //共享内存一般建议是4KB的整数倍
    //系统以4KB分配
    #define MAX_SIZE 4097//--- 内核会给你的,和你能用的,和你能用的是两码事

    key_t getKey()
    {
        key_t k = ftok(PATHNAME,PROJ_ID);//可以获得同样的一个Key!
        if(k < 0)
        {
            //cin, cout, cerr -> stdin, stdout, stderr -> 0, 1, 2
            std::cerr << errno << ":" << strerror(errno) << std::endl;
            exit(1);
        }
    }
    
    // k是要shmget,设置进入共享内存属性中的!用来表示
    //该共享内存,在内核中的唯一性!!

    //shmid vs key;
    //fd    vs inode
    int getShmHelper(key_t k, int flags)
    {
        int shmId = shmget(k, MAX_SIZE, flags);
        if(shmId < 0)
        {
            std::cerr << errno << ":" << strerror(errno) << std::endl;
            exit(2);
        }
        return shmId;
    }

    int getShm(key_t k)
    {
        return getShmHelper(k, IPC_CREAT | 0600);
    }

    int createShm(key_t k)
    {
        return getShmHelper(k, IPC_CREAT | IPC_EXCL | 0600);
    }

    void* attachShm(int shmid)
    {
        //int a = 10;
        //100u;// 字面值
        //纯数字没有任何意义的,必须得有类型才可以
        // 10u;
        // 10L;
        // 10;
        // 3.14f;
        //100元
        void* mem = shmat(shmid, nullptr, 0);//64位系统,8个字节
        if((long long)mem == -1L)
        {
            std::cerr << "shmat:" << errno << ":" << strerror(errno) << std::endl;
            exit(3);
        }
        return mem;
    }

    void detachShm(void *start)
    {
        if(shmdt(start) == -1)
        {
            std::cerr << "shmdt:" << errno << ":" << strerror(errno) << std::endl;
            exit(4);
        }
    }

    void delShm(int shmid)
    {
        if(shmctl(shmid, IPC_RMID, nullptr) == -1)
        {
            std::cerr << errno << ":" << strerror(errno) << std::endl;
        }
    }

#endif
